home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / macabuse / src / cop.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-20  |  33.2 KB  |  1,323 lines

  1. #include "lisp.hpp"
  2. #include "lisp_gc.hpp"
  3. #include "compiled.hpp"
  4. #include "objects.hpp"
  5. #include "level.hpp"
  6. #include "game.hpp"
  7. #include "jrand.hpp"
  8. #include "clisp.hpp"
  9. #include "ant.hpp"
  10. #include "key_cfg.hpp"
  11.  
  12. enum { point_angle, fire_delay1 };
  13.  
  14. #define SHOTGUN  10
  15. #define GRENADE  2
  16. #define ROCKET   3
  17. #define PLASMA   4
  18. #define FIREBOMB 5
  19. #define DFRIS    6
  20. #define LSABER   7
  21.  
  22. extern int registered;
  23.  
  24. signed char small_fire_off[24*2]=  // x & y offset from character to end of gun.
  25.   { 17,20,     // 1
  26.     17,23,     // 2
  27.     17,28,     
  28.     15,33,     
  29.     11,39,     // 5
  30.     7,43,
  31.     -3,44,     // 7
  32.     -10,42,    
  33.     -16,39,
  34.     -20,34,
  35.     -20,28,
  36.     -20,25,
  37.     -19,20,
  38.     -19,16,
  39.     -16,14,
  40.     -14,11,
  41.     -11,9,
  42.     -7,8,
  43.     -3,8,
  44.     2,8,
  45.     6,9,
  46.     10,10,
  47.     14,13,
  48.     16,15 };
  49.  
  50. signed char large_fire_off[24*2]=
  51.   { 18,25,
  52.     17,30,
  53.     15,34,
  54.     14,36,
  55.     10,39,
  56.     7,41,
  57.     4,42,
  58.     -3,41,
  59.     -8,39,
  60.     -11,37,
  61.     -14,33,
  62.     -16,30,
  63.     -18,25,
  64.     -17,21,
  65.     -14,17,
  66.     -11,15,
  67.     -7,13,
  68.     -4,12,
  69.     3,12,
  70.     9,12,
  71.     12,15,
  72.     14,16,
  73.     15,18,
  74.     16,21 };
  75.   
  76.  
  77. enum { in_climbing_area,
  78.     disable_top_draw,
  79.     just_hit,
  80.     ship_pan_x,
  81.     special_power,
  82.     used_special_power,
  83.     last1_x, last1_y,
  84.     last2_x, last2_y,
  85.     has_saved_this_level,
  86.     r_ramp, g_ramp, b_ramp,
  87.         is_teleporting,
  88.        just_fired};
  89.  
  90.  
  91. enum { sgb_speed,
  92.        sgb_angle,
  93.        sgb_lastx,
  94.        sgb_lasty,
  95.        sgb_bright_color,
  96.        sgb_medium_color,
  97.        sgb_lifetime };
  98.  
  99. enum { NO_POWER,
  100.        FAST_POWER,
  101.        FLY_POWER,
  102.        SNEAKY_POWER,
  103.        HEALTH_POWER } ;
  104.  
  105. enum { top_point_angle, 
  106.        top_fire_delay1, 
  107.        top_just_fired };
  108.  
  109. inline int angle_diff(int a1, int a2)
  110. {
  111.   if (a1<a2)
  112.   { if ((a2-a1)<180)
  113.       return a2-a1;
  114.     else return 360-a2+a1;
  115.   } else
  116.   {
  117.     if ((a1-a2)<180)
  118.       return a1-a2;
  119.     else return 360-a1+a2;
  120.   }
  121.   return 0;
  122. }
  123.  
  124. extern char *symbol_str(char *name);
  125.  
  126. void *top_ai()
  127. {
  128.   game_object *o=current_object;
  129.   if (o->total_objects())            // make sure we are linked to the main character
  130.   {  
  131.     game_object *q=o->get_object(0);
  132.  
  133.     view *v=q->controller();
  134.     if (v)
  135.     {
  136.       if (!v->freeze_time)
  137.       {
  138.     o->direction=1;                 // always face right
  139.  
  140.     if (q->direction<0)
  141.           q->x+=4;
  142.     int i; 
  143.     signed char *fire_off=o->otype==S_DFRIS_TOP ? large_fire_off :
  144.                                     (o->otype==S_ROCKET_TOP ? large_fire_off :
  145.                      (o->otype==S_BFG_TOP ? large_fire_off : small_fire_off));
  146.     signed char *f=fire_off,*fb;
  147.     int best_diff=200,best_num;
  148.     int iy=f[1],ix=f[6*2];
  149.     
  150.     int best_angle=lisp_atan2(q->y-iy-v->pointer_y,v->pointer_x-q->x-ix);
  151.     for (i=0;i<24;i++,f+=2)             // check all the angles to see which would best fit animation wise
  152.     {
  153.       int this_angle=lisp_atan2(f[1]-iy,f[0]-ix);
  154.       int this_diff=angle_diff(this_angle,best_angle);
  155.       if (this_diff<best_diff)
  156.       {
  157.         best_diff=this_diff;
  158.         best_num=i;
  159.         fb=f;
  160.       }
  161.     }
  162.  
  163.  
  164.     // if the pointer is too close to the player go with the angle shown, not the angle through the pointer
  165.     if (abs(q->y-fb[1]-v->pointer_y)<45 & abs(v->pointer_x-q->x+fb[0])<40)
  166.       o->lvars[point_angle]=lisp_atan2(fb[1]-iy,fb[0]-ix);
  167.     else
  168.       o->lvars[point_angle]=lisp_atan2(q->y-fb[1]-v->pointer_y,v->pointer_x-(q->x+fb[0]));
  169.     
  170.  
  171.     if (q->direction<0)
  172.           q->x-=4;
  173.  
  174.     o->x=q->x;
  175.     o->y=q->y+29-q->picture()->height();
  176.  
  177.     rand_on+=o->lvars[point_angle];
  178.     o->current_frame=best_num;
  179.  
  180.  
  181.     if (o->lvars[fire_delay1])
  182.       o->lvars[fire_delay1]--;
  183.  
  184.     o->otype=weapon_types[v->current_weapon];  // switch to correct top part    
  185.       }
  186.     }
  187.   }
  188.   return true_symbol;
  189. }
  190.  
  191.  
  192. int player_fire_weapon(game_object *o, int type, game_object *target, int angle, signed char *fire_off)
  193. {
  194.  
  195.   if (!o->total_objects()) return 0;
  196.   game_object *other=o->get_object(0);
  197.   int ox=other->x,oy=other->y;
  198.   if (other->direction<0) other->x+=4;
  199.  
  200.   int firex=other->x+fire_off[o->current_frame*2];
  201.   int firey=other->y-fire_off[o->current_frame*2+1];
  202.  
  203.  
  204.  
  205.   // fire try to move up to gun level
  206.  
  207.   long x2=o->x,y2=firey;
  208. //  current_level->foreground_intersect(other->x,other->y,x2,y2);      // find first location we can actuall "see"
  209. //  current_level->all_boundary_setback(o,other->x,other->y,x2,y2);       // to make we don't fire through walls
  210.   other->y=y2;
  211.  
  212.   if (other->y==firey)             // now try to move out to end of gun if we were not blocked above
  213.   {
  214.     x2=firex;
  215.     current_level->foreground_intersect(other->x,other->y,x2,y2);      // find first location we can actuall "see"
  216.     current_level->all_boundary_setback(other,other->x,other->y,x2,y2);       // to make we don't fire through walls
  217.     o->x=x2;
  218.   }
  219.  
  220.   void *list=NULL;
  221.   p_ref r1(list);
  222.   push_onto_list(new_lisp_pointer(target),list);
  223.   push_onto_list(new_lisp_number(angle),list);
  224.   push_onto_list(new_lisp_number(y2),list);
  225.   push_onto_list(new_lisp_number(x2),list);
  226.   push_onto_list(new_lisp_number(type),list);
  227.   push_onto_list(new_lisp_pointer(o->get_object(0)),list);
  228.   eval_function((lisp_symbol *)l_fire_object,list);
  229.   o->lvars[top_just_fired]=1;
  230.   other->lvars[just_fired]=1;
  231.   other->x=ox;
  232.   other->y=oy;
  233.  
  234.   return 1;
  235. }
  236.  
  237.  
  238.  
  239. void *laser_ufun(void *args)
  240. {
  241.   game_object *o=current_object;
  242.   p_ref r1(args);
  243.   void *signal=CAR(args);  args=CDR(args);
  244.   void *ret=NULL;
  245.  
  246.   if (signal==l_FIRE)
  247.   {
  248.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  249.     {
  250.       long value=lnumber_value(eval(CAR(args)));
  251.       if (value)                                   // do we have ammo ?
  252.       {
  253.     o->lvars[fire_delay1]=3;
  254.     if (player_fire_weapon(o,SHOTGUN,NULL,o->lvars[point_angle],small_fire_off))
  255.           ret=new_lisp_number(-1);
  256.     else ret=new_lisp_number(0);
  257.       } else
  258.       {
  259.     o->lvars[fire_delay1]=5;                  // no ammo, set large fire delay for next shot
  260.     player_fire_weapon(o,SHOTGUN,NULL,o->lvars[point_angle],small_fire_off);
  261.     ret=new_lisp_number(0);
  262.       }
  263.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  264.   }
  265.   return ret;
  266. }
  267.  
  268.  
  269. static int ammo_type(int otype)
  270. {
  271.   if (otype==S_GRENADE_TOP)
  272.     return GRENADE;
  273.   else if (otype==S_FIREBOMB_TOP)
  274.     return FIREBOMB;
  275.   else if (otype==S_DFRIS_TOP)
  276.     return DFRIS;
  277.   else return SHOTGUN;
  278. }
  279.  
  280.  
  281. void *top_ufun(void *args)                       // generic top character ai GRENADE && FIREBOMB
  282. {
  283.   game_object *o=current_object;
  284.   p_ref r1(args);
  285.   void *signal=CAR(args);  args=CDR(args);
  286.   void *ret=NULL;
  287.  
  288.   if (signal==l_FIRE)
  289.   {
  290.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  291.     {
  292.       long value=lnumber_value(eval(CAR(args)));
  293.       if (value)                                   // do we have ammo ?
  294.       {
  295.     o->lvars[fire_delay1]=6;
  296.     if (player_fire_weapon(o,ammo_type(o->otype),NULL,o->lvars[point_angle],
  297.                    o->otype==DFRIS ? large_fire_off : small_fire_off ))      
  298.           ret=new_lisp_number(-1);
  299.     else ret=new_lisp_number(0);
  300.       } else ret=new_lisp_number(0);
  301.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  302.   }
  303.   return ret;
  304. }
  305.  
  306. static int climb_handler(game_object *, int xm, int ym, int but);
  307.  
  308. void *plaser_ufun(void *args)
  309. {
  310.   game_object *o=current_object;
  311.   p_ref r1(args);
  312.   void *signal=CAR(args);  args=CDR(args);
  313.   void *ret=NULL;
  314.  
  315.   if (signal==l_FIRE)
  316.   {
  317.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  318.     {
  319.       long value=lnumber_value(eval(CAR(args)));
  320.       if (value)                                   // do we have ammo ?
  321.       {
  322.     o->lvars[fire_delay1]=2;
  323.     if (player_fire_weapon(o,PLASMA,NULL,o->lvars[point_angle],small_fire_off))      
  324.           ret=new_lisp_number(-1);
  325.     else ret=new_lisp_number(0);
  326.       } else ret=new_lisp_number(0);
  327.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  328.   }
  329.   return ret;
  330. }
  331.  
  332. void *lsaber_ufun(void *args)
  333. {
  334.   game_object *o=current_object;
  335.   p_ref r1(args);
  336.   void *signal=CAR(args);  args=CDR(args);
  337.   void *ret=NULL;
  338.  
  339.   if (signal==l_FIRE)
  340.   {
  341.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  342.     {
  343.       long value=lnumber_value(eval(CAR(args)));
  344.       if (value)                                   // do we have ammo ?
  345.       {
  346.     o->lvars[fire_delay1]=1;
  347.     if (player_fire_weapon(o,LSABER,NULL,o->lvars[point_angle]+(current_level->tick_counter()&7)-8,
  348.                    small_fire_off))
  349.           ret=new_lisp_number(-1);
  350.     else ret=new_lisp_number(0);
  351.       } else ret=new_lisp_number(0);
  352.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  353.   }
  354.   return ret;
  355. }
  356.  
  357.  
  358.  
  359. void *player_rocket_ufun(void *args)
  360. {
  361.   game_object *o=current_object;
  362.   p_ref r1(args);
  363.   void *signal=CAR(args);  args=CDR(args);
  364.   void *ret=NULL;
  365.   int xd,yd,cl=0xfffffff,d;
  366.   if (signal==l_FIRE)
  367.   {
  368.     if (!o->lvars[fire_delay1])                   // make sur we are not waiting of previous fire
  369.     {
  370.       long value=lnumber_value(eval(CAR(args)));
  371.       if (value)                                   // do we have ammo ?
  372.       {
  373.     o->lvars[fire_delay1]=6;
  374.     game_object *target=NULL,*p,*bot=o->total_objects() ? o->get_object(0) : 0;
  375.     if (bad_guy_array)
  376.     {
  377.       game_object *other=current_object->total_objects() ? current_object->get_object(0) : 0;
  378.       for (p=current_level->first_active_object();p;p=p->next_active)
  379.       {
  380.         xd=abs(p->x-o->x);
  381.         yd=abs(p->y-o->y);
  382.         if (xd<160 && yd<130 && bad_guy_array[p->otype] && p!=other)
  383.         {
  384.           if (p->targetable() &&          
  385.           !(p->otype==S_ROCKET && p->total_objects() && p->get_object(0)==bot))  // don't track onto own missles
  386.           {
  387.         d=xd*xd+yd*yd;
  388.         if (d<cl)
  389.         {
  390.           cl=d;
  391.           target=p;
  392.         }
  393.           }
  394.         }
  395.       }
  396.     }
  397.     if (player_fire_weapon(o,ROCKET,target,o->lvars[point_angle],large_fire_off))      
  398.           ret=new_lisp_number(-1);
  399.     else ret=new_lisp_number(0);
  400.  
  401.       } else ret=new_lisp_number(0);
  402.     } else ret=new_lisp_number(0);                // can't fire yet, return 0 ammo subtract
  403.   }
  404.   return ret;
  405. }
  406.  
  407. static int player_move(game_object *o, int xm, int ym, int but)
  408. {
  409.   if (!o->lvars[in_climbing_area])
  410.   {
  411.     if (o->state==S_climbing)
  412.     {
  413.       o->set_gravity(1);
  414.       o->set_state(run_jump_fall);
  415.     }
  416.     o->next_picture();
  417.     return o->mover(xm,ym,but);
  418.   } else return climb_handler(o,xm,ym,but);
  419.      
  420. }
  421.  
  422.  
  423. static void undo_special_power(game_object *o)
  424. {
  425.   switch (o->lvars[special_power])
  426.   {
  427.     case SNEAKY_POWER :
  428.     {
  429.       if (o->lvars[used_special_power]>0)
  430.         o->lvars[used_special_power]--;
  431.     } break;
  432.     case FAST_POWER :
  433.     {
  434.       o->lvars[used_special_power]=0;
  435.     } break;
  436.   }
  437. }
  438.  
  439. static void do_special_power(game_object *o, int xm, int ym, int but, game_object *top)
  440. {
  441.   switch (o->lvars[special_power])
  442.   {
  443.     case FLY_POWER :
  444.     {
  445.       if (registered)
  446.       {
  447.     game_object *cloud=create(S_CLOUD,o->x+o->direction*-10,o->y+jrand()%5);
  448.     if (current_level)
  449.         current_level->add_object(cloud);
  450.     o->set_state(run_jump);
  451.     o->set_gravity(1);
  452.     o->set_yacel(0);
  453.     if (o->yvel()>0) o->set_yvel(o->yvel()/2);
  454.     if (ym<0) 
  455.         o->set_yvel(o->yvel()-3);
  456.     else
  457.         o->set_yvel(o->yvel()-2);
  458.     the_game->play_sound(S_FLY_SND,32,o->x,o->y);
  459.       }
  460.     } break;
  461.     case FAST_POWER :
  462.     {
  463.       if ((current_level->tick_counter()%16)==0)
  464.       the_game->play_sound(S_SPEED_SND,100,o->x,o->y);
  465.  
  466.       o->lvars[used_special_power]=1;
  467.       o->lvars[last1_x]=o->x;
  468.       o->lvars[last1_y]=o->y;
  469.       long oyvel=o->yvel();
  470.       int in=o->lvars[in_climbing_area];
  471.       int ok;
  472.  
  473.  
  474.       player_move(o,xm,ym,but);
  475.       if (ym<0 && !oyvel && o->yvel()<0)             // if they just jumped, make them go higher
  476.       o->set_yvel(o->yvel()+o->yvel()/3);
  477.       o->lvars[in_climbing_area]=in;
  478.  
  479.       o->lvars[last2_x]=o->x;
  480.       o->lvars[last2_x]=o->y;
  481.     } break;
  482.     case SNEAKY_POWER :
  483.     {
  484.       if (registered)
  485.       {
  486.     if (o->lvars[used_special_power]<15)
  487.           o->lvars[used_special_power]++;
  488.       }
  489.     } break;
  490.   }
  491. }
  492.  
  493. static int climb_off_handler(game_object *o)
  494. {
  495.   if (o->next_picture())
  496.     o->controller()->pan_y-=4;
  497.   else
  498.   {
  499.     o->y-=28;
  500.     o->controller()->pan_y+=28;
  501.     o->controller()->last_y-=28;
  502.     o->set_state(stopped);
  503.   }
  504.   return 0;
  505. }
  506.  
  507.  
  508. static int climb_on_handler(game_object *o)
  509. {
  510.   if (o->next_picture())
  511.     o->controller()->pan_y+=4;
  512.   else
  513.     o->set_state((character_state)S_climbing);
  514.   return 0;
  515. }
  516.  
  517. static int climb_handler(game_object *o, int xm, int ym, int but)
  518. {
  519.   int yd=o->lvars[in_climbing_area];  // see how from the top we are
  520.   o->lvars[in_climbing_area]=0;          // set 0, ladders will set back to proper if still in area
  521.   if (o->state==S_climb_off)
  522.     climb_off_handler(o);
  523.   else if (o->state==S_climb_on)
  524.     climb_on_handler(o);  
  525.   else
  526.   {
  527.     if (o->state==S_climbing)
  528.     {
  529.       if (ym>0)                       // going down
  530.       {
  531.  
  532.     if (o->current_frame==0) o->current_frame=9;
  533.       o->current_frame--;    
  534.  
  535. /*    if (o->lvars[special_power]==FAST_POWER)
  536.     {
  537.       long xv=0,yv=4;
  538.       o->try_move(o->x,o->y,xv,yv,1);
  539.       if (yv==4)
  540.         o->y+=3;
  541.       else 
  542.       {
  543.         o->set_gravity(1);
  544.           o->set_state(run_jump_fall);
  545.       }
  546.     }
  547.     else */ o->y+=3;
  548.     
  549.  
  550.       } else if (ym<0)
  551.       {
  552.     if (yd<32)
  553.       o->set_state((character_state)S_climb_off);
  554.     else
  555.     {
  556.       if (!o->next_picture()) o->set_state((character_state)S_climbing);
  557.       o->y-=3;
  558.     }
  559.       }
  560.       if (xm)                     // trying to get off the ladder, check to see if that's ok
  561.       {
  562.     long x2=0,y2=-20;
  563.     o->try_move(o->x,o->y,x2,y2,3);
  564.     if (y2==-20)
  565.     {
  566.       o->set_gravity(1);
  567.       if (ym>=0)
  568.         o->set_state(run_jump_fall);
  569.       else 
  570.       { o->set_state(run_jump);
  571.         o->set_yvel(get_ability(o->otype,jump_yvel));      
  572.       }
  573.     }
  574.       }
  575.     }  else if (ym>0 && yd<10)
  576.     {
  577.       o->y+=28;
  578.       o->controller()->pan_y-=28;
  579.       o->controller()->last_y+=28;
  580.       o->set_state((character_state)S_climb_on);
  581.     }
  582.     else if (o->yvel()>=0 && (ym>0 || (ym<0 && yd>8)))
  583.     {
  584.       o->set_state((character_state)S_climbing);
  585.       o->set_gravity(0);
  586.       o->set_xvel(0);
  587.       o->set_yvel(0);
  588.       o->set_xacel(0);
  589.       o->set_yacel(0);
  590.       return 0;
  591.     } else 
  592.     { 
  593.       o->next_picture();
  594.       return o->mover(xm,ym,but);
  595.     }
  596.   }
  597.   return 0;
  598. }
  599.  
  600.  
  601. void *cop_mover(int xm, int ym, int but)
  602. {
  603.  
  604.   int ret=0;
  605.   game_object *o=current_object,*top;
  606.   if (o->controller() && o->controller()->freeze_time)  
  607.   {
  608.     o->controller()->freeze_time--;
  609.     if (but || o->controller()->key_down(JK_SPACE) || o->controller()->key_down(JK_ENTER)) 
  610.       o->controller()->freeze_time=0;
  611.   }
  612.   else
  613.   {
  614.     if (!o->total_objects())                  // if no top create one
  615.     {
  616.       top=create(S_MGUN_TOP,o->x,o->y,0,0);
  617.       current_level->add_object_after(top,o);    
  618.       o->add_object(top);
  619.       top->add_object(o);
  620.     } else top=o->get_object(0);
  621.  
  622.     if (o->yvel()>10) 
  623.     {
  624.       o->set_yacel(0);
  625.       o->set_yvel(o->yvel()-1);            // terminal velocity
  626.     }
  627.  
  628.     if (o->aistate()==0)  // just started, wait for button
  629.     {
  630.       o->set_aistate(1);    
  631.     } else if (o->aistate()==1)         // normal play
  632.     {
  633.       if (o->hp()==0)
  634.       {
  635.     o->set_aistate(2);                // go to deing state
  636.     o->set_state(dead);    
  637.       }
  638.       else
  639.       {
  640.     if (o->hp()<40 && (current_level->tick_counter()%16)==0) // if low on health play heart beat    
  641.       the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
  642.     else if (o->hp()<15 && (current_level->tick_counter()%8)==0) // if low on health play heart beat
  643.       the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
  644.     else if (o->hp()<7 && (current_level->tick_counter()%4)==0) // if low on health play heart beat
  645.       the_game->play_sound(S_LOW_HEALTH_SND,127,o->x,o->y);
  646.  
  647.     if (but&1)
  648.         do_special_power(o,xm,ym,but,top);
  649.     else
  650.     undo_special_power(o);
  651.     ret=player_move(o,xm,ym,but);
  652.     top->x=o->x;
  653.     top->y=o->y+29-top->picture()->height();
  654.     
  655.     if ((but&2) && !o->lvars[is_teleporting] && o->state!=S_climbing && o->state!=S_climb_off)
  656.     {
  657.       void *args=NULL;
  658.       p_ref r1(args);
  659.       view *v=o->controller();
  660.  
  661.       push_onto_list(new_lisp_number(v->weapon_total(v->current_weapon)),args);
  662.       push_onto_list(l_FIRE,args);
  663.  
  664.       current_object=top;
  665.       void *ret=eval_function((lisp_symbol *)figures[top->otype]->get_fun(OFUN_USER_FUN),args);      
  666.       current_object=o;
  667.       v->add_ammo(v->current_weapon,lnumber_value(ret));    
  668.     }
  669.       }    
  670.     } else if (o->aistate()==3)
  671.     {
  672.       if (!o->controller() || o->controller()->key_down(JK_SPACE))
  673.       {
  674.          int old_kills=o->controller()->kills;   // this i s bit of a hack, save the kills
  675.     eval_function((lisp_symbol *)l_restart_player,NULL);  // call teh user function to reset the player
  676.     o->controller()->reset_player();
  677.     if (player_list->next)
  678.       o->controller()->kills=old_kills;  // if a multiplayer game restore their kills
  679.     o->set_aistate(0);     
  680.       } else if (o->controller() && o->controller()->local_player())
  681.         the_game->show_help(symbol_str("space_cont"));
  682.  
  683.     } else o->set_aistate(o->aistate()+1);
  684.   }
  685.  
  686.   return new_lisp_number(ret);
  687. }
  688.  
  689.  
  690.  
  691. void *ladder_ai()
  692. {
  693.   view *f=player_list;
  694.   game_object *o=current_object;
  695.   if (o->total_objects())
  696.   {
  697.     game_object *other=o->get_object(0);
  698.     for (;f;f=f->next)
  699.     {
  700.       int mex=f->focus->x;
  701.       int mey=f->focus->y;
  702.       
  703.       if (o->x<=mex && o->y<=mey && other->x>=mex && other->y>=mey)
  704.       {
  705.     if (f->focus->state==S_climbing)
  706.       f->focus->x=(o->x+other->x)/2;
  707.         f->focus->lvars[in_climbing_area]=mey-o->y;    
  708.       }
  709.     }
  710.   }
  711.   return true_symbol;
  712. }
  713.  
  714.  
  715.  
  716. void *player_draw(int just_fired_var, int num)
  717. {
  718.   game_object *o=current_object;
  719.   if (num==0) 
  720.   {
  721.     if (o->lvars[just_fired_var])
  722.     {
  723.       o->draw_tint(S_bright_tint);
  724.       o->lvars[just_fired_var]=0;
  725.     } else
  726.       o->drawer();
  727.   }
  728.   else 
  729.   {
  730.     if (o->lvars[just_fired_var])
  731.     {
  732.       o->draw_double_tint(lnumber_value(lget_array_element(symbol_value(l_player_tints),num)),S_bright_tint);
  733.       o->lvars[just_fired_var]=0;
  734.     } else
  735.       o->draw_tint(lnumber_value(lget_array_element(symbol_value(l_player_tints),num)));
  736.   }
  737.   return NULL;
  738. }
  739.  
  740.  
  741. void *top_draw()
  742. {
  743.   game_object *o=current_object;
  744.   if (o->total_objects())
  745.   {
  746.     game_object *bot=o->get_object(0);
  747.     if (bot->state==stopped  || bot->state==running || 
  748.     bot->state==run_jump || bot->state==run_jump_fall ||
  749.     bot->state==end_run_jump)
  750.     {
  751.       int oldy=o->y;
  752.       o->x=bot->x;
  753.       if (bot->direction<0)
  754.         o->x+=4;
  755.       o->y=bot->y+29-bot->picture()->height();
  756.  
  757.       void *ret=NULL;
  758.       p_ref r1(ret);
  759.  
  760.       push_onto_list(new_lisp_number(bot->controller()->player_number),ret);
  761.  
  762.       if (bot->lvars[special_power]==SNEAKY_POWER)
  763.       {
  764.     if (bot->lvars[used_special_power]==0)
  765.       player_draw(top_just_fired,bot->controller()->player_number);
  766.     else if (bot->lvars[used_special_power]<15)
  767.       o->draw_trans(bot->lvars[used_special_power],16);
  768.     else
  769.       o->draw_predator();
  770.       } else
  771.         eval_function((lisp_symbol *)l_player_draw,ret);
  772.       
  773.       o->y=oldy;
  774.       if (bot->direction<0)
  775.         o->x-=4;
  776.     }
  777.   }
  778.   return NULL;
  779. }
  780.  
  781.  
  782.  
  783. void *bottom_draw()
  784. {
  785.   game_object *o=current_object;
  786.  
  787.   if (o->lvars[r_ramp] || o->lvars[g_ramp] || o->lvars[b_ramp])
  788.   {
  789.     int r=o->lvars[r_ramp];
  790.     if (r>7) r-=7;
  791.     else r=0;
  792.     o->lvars[r_ramp]=r;
  793.  
  794.     int g=o->lvars[g_ramp];
  795.     if (g>7) g-=7;
  796.     else g=0;
  797.     o->lvars[g_ramp]=g;
  798.  
  799.     int b=o->lvars[b_ramp];
  800.     if (b>7) b-=7;
  801.     else b=0;
  802.     o->lvars[b_ramp]=b;
  803.  
  804.     palette *p=pal->copy();
  805.     uchar *addr=(uchar *)p->addr();
  806.     int ra,ga,ba;
  807.     
  808.     for (int i=0;i<256;i++)
  809.     {
  810.       ra=(int)*addr+r; if (ra>255) ra=255; else if (ra<0) r=0; *addr=(uchar)ra; addr++;
  811.       ga=(int)*addr+g; if (ga>255) ga=255; else if (ga<0) g=0; *addr=(uchar)ga; addr++;
  812.       ba=(int)*addr+b; if (ba>255) ba=255; else if (ba<0) b=0; *addr=(uchar)ba; addr++;
  813.     }
  814.     p->load();
  815.     delete p;
  816.   }
  817.  
  818.   if (o->aistate()>0)
  819.   {
  820.     switch (o->lvars[special_power])
  821.     {
  822.       case NO_POWER : 
  823.       { player_draw(just_fired,o->controller()->player_number); } break;
  824.  
  825.       case HEALTH_POWER :
  826.       {
  827.     player_draw(just_fired,o->controller()->player_number);
  828.     if (o->controller() && o->controller()->local_player())
  829.       cash.img(S_health_image)->put_image(screen,o->controller()->cx2-20,
  830.                         o->controller()->cy1+5,1);
  831.       } break;
  832.       case FAST_POWER :
  833.       {
  834.     eval_function((lisp_symbol *)l_draw_fast,NULL);
  835.     int old_state=o->state;
  836.     switch (o->state)
  837.     {
  838.       case stopped : o->state=(character_state)S_fast_stopped; break;
  839.       case running : o->state=(character_state)S_fast_running; break;
  840.       case start_run_jump : o->state=(character_state)S_fast_start_run_jump; break;
  841.       case run_jump : o->state=(character_state)S_fast_run_jump; break;
  842.       case run_jump_fall : o->state=(character_state)S_fast_run_jump_fall; break;
  843.       case end_run_jump : o->state=(character_state)S_fast_end_run_jump; break;
  844.     }
  845.  
  846.     player_draw(just_fired,o->controller()->player_number);
  847.     o->state=(character_state)old_state;
  848.     if (o->controller() && o->controller()->local_player())
  849.       cash.img(S_fast_image)->put_image(screen,o->controller()->cx2-20,
  850.                         o->controller()->cy1+5,1);
  851.       } break;
  852.       case FLY_POWER :
  853.       {
  854.     int old_state=o->state;
  855.     switch (o->state)
  856.     {
  857.       case stopped : o->state=(character_state)S_fly_stopped; break;
  858.       case running : o->state=(character_state)S_fly_running; break;
  859.       case start_run_jump : o->state=(character_state)S_fly_start_run_jump; break;
  860.       case run_jump : o->state=(character_state)S_fly_run_jump; break;
  861.       case run_jump_fall : o->state=(character_state)S_fly_run_jump_fall; break;
  862.       case end_run_jump : o->state=(character_state)S_fly_end_run_jump; break;
  863.     }
  864.  
  865.     player_draw(just_fired,o->controller()->player_number);
  866.     o->state=(character_state)old_state;
  867.  
  868.     if (o->controller() && o->controller()->local_player())
  869.       cash.img(S_fly_image)->put_image(screen,o->controller()->cx2-20,
  870.                         o->controller()->cy1+5,1);
  871.       } break;
  872.       case SNEAKY_POWER :
  873.       {
  874.     if (o->lvars[used_special_power]==0)
  875.       player_draw(just_fired,o->controller()->player_number);
  876.     else if (o->lvars[used_special_power]<15)
  877.       o->draw_trans(o->lvars[used_special_power],16);
  878.     else
  879.       o->draw_predator();
  880.       
  881.     if (o->controller() && o->controller()->local_player())
  882.       cash.img(S_sneaky_image)->put_image(screen,o->controller()->cx2-20,
  883.                         o->controller()->cy1+5,1);
  884.       } break;
  885.     }    
  886.   }
  887.   return NULL;
  888. }
  889.  
  890.  
  891.  
  892. void *sgun_ai()
  893. {
  894.   game_object *o=current_object;
  895.  
  896.   if (o->lvars[sgb_lifetime]==0)
  897.     return NULL;
  898.   o->lvars[sgb_lifetime]--;
  899.  
  900.   o->lvars[sgb_lastx]=o->x;
  901.   o->lvars[sgb_lasty]=o->y;
  902.   o->lvars[sgb_speed]=o->lvars[sgb_speed]*6/5;
  903.   
  904.   long ang=o->lvars[sgb_angle];
  905.   long mag=o->lvars[sgb_speed];
  906.  
  907.   long xvel=(lisp_cos(ang))*(mag);
  908.   current_object->set_xvel(xvel>>16);
  909.   current_object->set_fxvel((xvel&0xffff)>>8);
  910.   long yvel=-(lisp_sin(ang))*(mag);
  911.   current_object->set_yvel(yvel>>16);
  912.   current_object->set_fyvel((yvel&0xffff)>>8);      
  913.  
  914.  
  915.   int whit=0;
  916.   game_object *who=o->bmove(whit, o->total_objects() ? o->get_object(0) : 0);
  917.  
  918.   if (whit || (who && figures[who->otype]->get_cflag(CFLAG_UNACTIVE_SHIELD) && who->total_objects() &&
  919.            who->get_object(0)->aistate()==0))
  920.   {
  921.     o->lvars[sgb_lifetime]=0;
  922.     game_object *n=create(S_EXPLODE5,o->x+jrand()%4,o->y+jrand()%4);
  923.     current_level->add_object(n);    
  924.   } else if (who && figures[who->otype]->get_cflag(CFLAG_HURTABLE))
  925.   {
  926.     o->lvars[sgb_lifetime]=0;
  927.     game_object *n=create(S_EXPLODE3,o->x+jrand()%4,o->y+jrand()%4);
  928.     current_level->add_object(n);        
  929.      who->do_damage(5,o,o->x,o->y,(lisp_cos(ang)*10)>>16,(lisp_sin(ang)*10)>>16);
  930.   }
  931.   return true_symbol;
  932. }
  933.  
  934.  
  935.  
  936. void *mover_ai()
  937. {
  938.   game_object *o=current_object;
  939.   if (o->total_objects()==2)
  940.   {
  941.     if (o->aistate()<2) 
  942.     {
  943.       game_object *obj=o->get_object(1);
  944.       o->remove_object(obj);
  945.       game_object *d=o->get_object(0);
  946.       d->add_object(obj);
  947.       d->set_aistate(d->aitype());
  948.     } else
  949.     {
  950.       o->set_aistate(o->aistate()-1);
  951.       game_object *d=o->get_object(0);
  952.       game_object *obj=o->get_object(1);      
  953.  
  954.       obj->x=d->x-(d->x-o->x)*o->aistate()/o->aitype();
  955.       obj->y=d->y-(d->y-o->y)*o->aistate()/o->aitype();
  956.     }
  957.   }
  958.   return true_symbol;
  959. }    
  960.  
  961.  
  962. void *respawn_ai()
  963.  game_object *o=current_object;
  964.  int x=o->total_objects();
  965.  if (x)
  966.  {
  967.    game_object *last=o->get_object(x-1);
  968.    if (last->x==o->x && last->y==o->y)
  969.    {
  970.      if (last->fade_count())
  971.        last->set_fade_count(last->fade_count()-1);
  972.      o->set_aistate_time(0);
  973.    } else if (o->aistate_time()>o->xvel())
  974.    {
  975.      int type=o->get_object(jrandom(x))->otype;
  976.      game_object *n=create(type,o->x,o->y);
  977.      current_level->add_object(n);
  978.      o->add_object(n);
  979.      n->set_fade_count(15);
  980.      o->set_aistate_time(0);
  981.    } 
  982.  }
  983.  return true_symbol;
  984. }
  985.  
  986. static int compare_players(const void *a, const void *b)
  987. {
  988.   if  ( ((view **)a)[0]->kills > ((view **)b)[0]->kills) 
  989.     return -1;
  990.   else if  ( ((view **)a)[0]->kills < ((view **)b)[0]->kills) 
  991.     return 1;
  992.   else if (((view **)a)[0]->player_number > ((view **)b)[0]->player_number)
  993.     return -1;
  994.   else if (((view **)a)[0]->player_number < ((view **)b)[0]->player_number)
  995.     return 1;
  996.   else return 0;  
  997. }
  998.  
  999. void *score_draw()
  1000. {
  1001.   view *sorted_players[16],*local=NULL;
  1002.   int tp=0;
  1003.   view *f=player_list;
  1004.   for (;f;f=f->next) 
  1005.   { 
  1006.     sorted_players[tp]=f;
  1007.     tp++;
  1008.     if (f->local_player()) local=f;
  1009.   }
  1010.  
  1011.   JCFont *fnt=eh->frame_font();
  1012.   if (local)
  1013.   {
  1014.     qsort(sorted_players,tp,sizeof(view *),compare_players);
  1015.  
  1016.     int x=local->cx1;
  1017.     int y=local->cy1;
  1018.     char msg[100];
  1019.  
  1020.     int i;
  1021.     for (i=0;i<tp;i++)
  1022.     {
  1023.       int color=lnumber_value(lget_array_element(symbol_value(l_player_text_color),sorted_players[i]->player_number));  
  1024.       sprintf(msg,"%3d %s",sorted_players[i]->kills,sorted_players[i]->name);
  1025.       if (sorted_players[i]==local)
  1026.         strcat(msg," <<");
  1027.  
  1028.       fnt->put_string(screen,x,y,msg,color);
  1029.       y+=fnt->height();
  1030.     }
  1031.   }
  1032.   return NULL;
  1033. }
  1034.  
  1035.  
  1036. extern void fade_in(image *im, int steps);
  1037. extern void fade_out(int steps);
  1038.  
  1039. void *show_kills()
  1040. {
  1041.   fade_out(8);
  1042.   eh->set_mouse_position(0,0);
  1043.   screen->clear();
  1044.  
  1045.   switch_mode(VMODE_640x480);
  1046.  
  1047.   int xp,yp;
  1048.   load_image_into_screen("art/frame.spe","end_level_screen",xp,yp);
  1049.  
  1050.   int x1=xp+342,y1=yp,x2=xp+639,y2=yp+294;
  1051.  
  1052.   JCFont *fnt=eh->font();
  1053.   fade_in(NULL,16);
  1054.   
  1055.   view *v=player_list; int tp=0,i;
  1056.   for (v=player_list;v;v=v->next) tp++;
  1057.  
  1058.   int y=(y1+y2)/2-(tp+2)*fnt->height()/2,x=x1+10;
  1059.   char *header_str=symbol_str("score_header");
  1060.   fnt->put_string(screen,x,y,header_str,eh->bright_color());
  1061.   y+=fnt->height();
  1062.  
  1063.   screen->wiget_bar(x,y+2,x+strlen(header_str)*fnt->width(),y+fnt->height()-3,
  1064.              eh->bright_color(),eh->medium_color(),eh->dark_color());
  1065.   y+=fnt->height();
  1066.   v=player_list;
  1067.   for (i=0;i<tp;i++)
  1068.   {
  1069.     enum { NAME_LEN=18 } ;
  1070.     int color=lnumber_value(lget_array_element(symbol_value(l_player_text_color),v->player_number));  
  1071.     char max_name[NAME_LEN];
  1072.     strncpy(max_name,v->name,NAME_LEN-1);
  1073.     max_name[NAME_LEN-1]=0;
  1074.     char msg[100];
  1075.  
  1076.  
  1077.     sprintf(msg,"%-17s %3d  %3d",max_name,v->kills,v->tkills+v->kills);
  1078.     fnt->put_string(screen,x,y,msg,color);
  1079.  
  1080.     y+=fnt->height();
  1081.     v=v->next;
  1082.   }
  1083.   
  1084.   eh->flush_screen();
  1085.   milli_wait(4000);   // wait 4 seconds
  1086.  
  1087.   return NULL;
  1088. }
  1089.  
  1090.  
  1091.  
  1092. static void give_weapons(game_object *player, ushort otype)
  1093. {
  1094.   view *v=player->controller();
  1095.   if (!v)
  1096.   {
  1097.     lbreak("object has no controller");
  1098.     exit(0);
  1099.   }
  1100.  
  1101.   int w_type=-1;
  1102.  
  1103.   if (otype==lnumber_value(symbol_value(l_MBULLET_ICON5)) || otype==lnumber_value(symbol_value(l_MBULLET_ICON20)))
  1104.     w_type=0;
  1105.  
  1106.   else if (otype==lnumber_value(symbol_value(l_GRENADE_ICON2)) || otype==lnumber_value(symbol_value(l_GRENADE_ICON10)))
  1107.     w_type=1;
  1108.  
  1109.   else if (otype==lnumber_value(symbol_value(l_ROCKET_ICON2)) || otype==lnumber_value(symbol_value(l_ROCKET_ICON5)))
  1110.     w_type=2;
  1111.  
  1112.   else if (otype==lnumber_value(symbol_value(l_FBOMB_ICON1)) || otype==lnumber_value(symbol_value(l_FBOMB_ICON5)))
  1113.     w_type=3;
  1114.  
  1115.   else if (otype==lnumber_value(symbol_value(l_PLASMA_ICON20)) || otype==lnumber_value(symbol_value(l_PLASMA_ICON50)))
  1116.     w_type=4;
  1117.  
  1118.   else if (otype==lnumber_value(symbol_value(l_LSABER_ICON50)) || otype==lnumber_value(symbol_value(l_LSABER_ICON100)))
  1119.     w_type=5;
  1120.  
  1121.   else if (otype==lnumber_value(symbol_value(l_DFRIS_ICON4)) || otype==lnumber_value(symbol_value(l_DFRIS_ICON10)))
  1122.     w_type=6;
  1123.  
  1124.  
  1125.   if (w_type!=-1)
  1126.   {   
  1127.     if (!v->has_weapon(w_type))
  1128.     {
  1129.       v->give_weapon(w_type);
  1130.       if (symbol_value(l_change_on_pickup))
  1131.         v->current_weapon=w_type;
  1132.     }
  1133.  
  1134.  
  1135.  
  1136.     v->add_ammo(w_type,get_ability(otype,start_hp));
  1137.   }
  1138. }
  1139.  
  1140. void *weapon_icon_ai()
  1141. {
  1142.   game_object *o=current_object;
  1143.   int try_fall=0;
  1144.  
  1145.  
  1146.   if (o->aistate()==0) // state 0 means we are stationary
  1147.   {
  1148.     if (o->total_objects()==0)
  1149.     {
  1150.       if ((jrand()%4)==0)  // check to see if we should fall approx ever 4 ticks
  1151.         try_fall=1;
  1152.     } else if (o->get_object(0)->aistate()==1)  // see if the object we are attached to is on
  1153.       try_fall=1;
  1154.   } else if (o->aistate()==1) // state 1 means we are currently falling
  1155.     try_fall=1;
  1156.  
  1157.  
  1158.   if (try_fall)
  1159.   {
  1160.     long x2=0,y2=10;
  1161.     game_object *who=o->try_move(o->x,o->y,x2,y2,3);                // see if we can fall 
  1162.     
  1163.  
  1164.     if (y2==0)
  1165.     {
  1166.       if (who)
  1167.         o->set_aistate(0);     // we are on top of another object and we need to continue checking for falling
  1168.       else o->set_aistate(2);  // we are on the ground, don't check for flaling anymore
  1169.     } else
  1170.     {
  1171.       o->y+=y2;
  1172.       o->set_aistate(1);  // we are in flight, continue falling        
  1173.     }
  1174.   }
  1175.  
  1176.   
  1177.   long x1,y1,x2,y2,xp1,yp1,xp2,yp2;
  1178.  
  1179.   game_object *player=current_level->attacker(current_object);
  1180.   player->picture_space(x1,y1,x2,y2);
  1181.   current_object->picture_space(xp1,yp1,xp2,yp2);
  1182.   if (!(xp1>x2 || xp2<x1 || yp1>y2 || yp2<y1))
  1183.   {
  1184.     the_game->play_sound(lnumber_value(symbol_value(l_ammo_snd)),127,o->x,o->y);
  1185.     give_weapons(player,o->otype);
  1186.     return NULL;
  1187.   }
  1188.   
  1189.   return true_symbol;
  1190. }
  1191.  
  1192.  
  1193.  
  1194. void *on_draw()
  1195. {
  1196.   game_object *o=current_object;
  1197.   if (o->total_objects()==0 || o->get_object(0)->aistate() || (dev&EDIT_MODE))
  1198.     o->drawer();  
  1199.   return 0;
  1200. }
  1201.  
  1202. void *tp2_ai()
  1203. {
  1204.   enum { tp_waiting, tp_fading };
  1205.  
  1206.  
  1207.   game_object *o=current_object;
  1208.   if (o->total_objects())
  1209.   {
  1210.     if (o->aistate()==0)  // wait for player to activate us
  1211.     {
  1212.       game_object *p=current_level->attacker(o);
  1213.  
  1214.       if (p->x>o->x-15 && p->x<o->x+15 && p->y>o->y-30 && p->y<o->y && p->controller()->y_suggestion>0)
  1215.       {
  1216.         o->add_object(p);
  1217.         o->set_aistate(tp_fading);
  1218.         the_game->play_sound(lnumber_value(symbol_value(l_TELEPORTER_SND)),127,o->x,o->y);
  1219.         o->set_state(running);
  1220.       }
  1221.     } else
  1222.     {
  1223.       game_object *p=o->get_object(1);
  1224.       if (o->next_picture())
  1225.       {
  1226.         p->x=o->x;
  1227.         p->y=o->y-16;
  1228.         int f=o->current_frame<16 ? o->current_frame : 15;
  1229.  
  1230.         p->set_fade_count(f);
  1231.         p->get_object(0)->set_fade_count(f);
  1232.         p->lvars[is_teleporting]=1;      
  1233.       } else
  1234.       {
  1235.         p->x=o->get_object(0)->x;
  1236.         p->y=o->get_object(0)->y-16;
  1237.         p->lvars[is_teleporting]=0;
  1238.         p->set_fade_count(0);
  1239.         p->get_object(0)->set_fade_count(0);
  1240.         o->remove_object(p);
  1241.         o->set_aistate(tp_waiting);
  1242.       }
  1243.     }
  1244.   }
  1245.   return true_symbol;
  1246. }
  1247.  
  1248.  
  1249.  
  1250. void *push_char(void *args)
  1251. {
  1252.   long xa=lnumber_value(CAR(args));
  1253.   long ya=lnumber_value(CAR(args));
  1254.  
  1255.   game_object *o=current_object;
  1256.   game_object *p=current_level->attacker(o);
  1257.   
  1258.   if (p->y<=o->y && abs(p->y-o->y)<ya && abs(p->x-o->x)<xa)
  1259.   {
  1260.     long amount;
  1261.     if (p->x>o->x)
  1262.       amount=xa-(p->x-o->x);
  1263.     else amount=(o->x-p->x)-xa;
  1264.     long yv=0;
  1265.     p->try_move(p->x,p->y,amount,yv,3);
  1266.     p->x+=amount;
  1267.   }
  1268.     return 0;
  1269. }
  1270.  
  1271. void *gun_draw()
  1272. {
  1273.   game_object *o=current_object;
  1274.   o->draw_tint(lnumber_value(lget_array_element(symbol_value(l_gun_tints),o->aitype())));
  1275.   return 0;
  1276. }
  1277.  
  1278.  
  1279. void *ant_draw()
  1280. {
  1281.   game_object *o=current_object;
  1282.   if (o->aitype()==0)
  1283.     o->drawer();
  1284.   else
  1285.     o->draw_tint(lnumber_value(lget_array_element(symbol_value(l_ant_tints),o->aitype())));
  1286.   return 0;
  1287. }
  1288.  
  1289. void *middle_draw()
  1290. {
  1291.   game_object *o=current_object;
  1292.   int y=o->y;
  1293.   o->y+=o->picture()->height()/2;
  1294.   o->drawer();
  1295.   o->y=y;
  1296.   return 0;
  1297. }
  1298.  
  1299. void *exp_draw()
  1300. {
  1301.   game_object *o=current_object;
  1302.   if (o->aitype()==0)
  1303.     middle_draw();
  1304.   return 0;
  1305. }
  1306.  
  1307. void *exp_ai()
  1308. {
  1309.   game_object *o=current_object;
  1310.   if (o->aitype()==0)
  1311.   {
  1312.     if (o->next_picture())
  1313.       return true_symbol;
  1314.     else return 0;
  1315.   }       
  1316.   else
  1317.   {
  1318.     o->set_aitype(o->aitype()-1);
  1319.     return true_symbol;
  1320.   }
  1321. }
  1322.